package com.chentf.reggie.java8;

import com.chentf.reggie.ReggieApplication;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.jni.Local;
import org.apache.tomcat.jni.Time;
import org.junit.Test;
import org.springframework.boot.test.context.SpringBootTest;

import javax.servlet.annotation.WebFilter;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Date;

/**
 * @author chentengfei
 * @desc java8日期时间demo
 * @date 2022-09-25 21:06:31
 */
@SpringBootTest(classes = {ReggieApplication.class})
@Slf4j
public class DateDemo {

    //获取当前时间
    @Test
    public void getCurrentDate(){
        LocalDate localDate = LocalDate.now();
        log.info("当前日期:{}",localDate);

        Date date = new Date();
        log.info("date当前日期:{}",date);
    }

    //获取年,月,日信息
    @Test
    public void getDetailDate(){
        LocalDate localDate = LocalDate.now();
        int year = localDate.getYear();
        int month = localDate.getMonthValue();
        int day = localDate.getDayOfMonth();
        System.out.printf("Year:%d Month:%d day:%d t %n",year,month,day);
    }

    //处理特定日期
    @Test
    public void handleSpecilDate(){
        LocalDate localDate = LocalDate.of(2022, 9,25);
        log.info("当前日期:{}", localDate);
    }

    //判断两个日期是否相等
    @Test
    public void compareDate(){
        LocalDate localDate = LocalDate.now();
        LocalDate localDate1 = LocalDate.of(2022, 9, 25);
        //LocalDate重载了equals方法,如果比较的日期是字符型,需要先解析成日期对象在进行判断
        if(localDate.equals(localDate1)){
            log.info("两个日期相等,{},{}", localDate,localDate1);
        }
    }

    //检查像生日这种周期性事件
    @Test
    public void cycleDate(){
        LocalDate today = LocalDate.now();
        LocalDate dateOfBirth = LocalDate.of(1990, 1, 15);

        MonthDay birthDay = MonthDay.of(dateOfBirth.getMonth(), dateOfBirth.getDayOfMonth());
        MonthDay currentMonthDay = MonthDay.from(today);

        if(currentMonthDay.equals(birthDay)){
            log.info("今天是你的生日:{}" , currentMonthDay);
        }else{
            log.info("今天不是你的生日:{}",currentMonthDay);
        }
    }

    //获取当前时间
    @Test
    public void getCurrentTime(){
        LocalTime localTime = LocalTime.now();
        log.info("当期时间:{}", localTime);
    }

    //在现有的时间上增加小时
    @Test
    public void plusHours(){
        LocalTime localTime = LocalTime.now();
        LocalTime newTime = localTime.plusHours(2); //增加2小时
        log.info("增加后的时间为:{}", newTime);
    }

    //如何计算一个星期之后的日期
    @Test
    public void nextWeek(){
        //LocalDate日期不包含时间信息，它的plus()方法用来增加天、周、月，ChronoUnit类声明了这些时间单位。由于LocalDate也是不变类型，返回后一定要用变量赋值
        LocalDate today = LocalDate.now();
        LocalDate nextWeek = today.plus(1, ChronoUnit.WEEKS);//使用变量赋值
        log.info("当期日期:{}",today);
        log.info("1周后的日期:{}",nextWeek);
    }

    //计算一年前或者一年后的日期
    @Test
    public void minusDate(){
        //LocalDate 的 plus() 方法增加天数、周数或月数
        LocalDate today = LocalDate.now();
        LocalDate previousYear = today.minus(1,ChronoUnit.YEARS);
        log.info("一年前的时间:{}", previousYear);

        LocalDate nexYear = today.plus(1,ChronoUnit.YEARS);
        log.info("一年后的时间:{}",nexYear);
    }

    //使用java8的Clock时钟类
    @Test
    public void clock(){
        //Java 8增加了一个 Clock 时钟类用于获取当时的时间戳，或当前时区下的日期时间信息。以前用到System.currentTimeInMillis() 和 TimeZone.getDefault() 的地方都可用Clock替换。
        //根据系统时间返回当前时间并设置UTC
        Clock clock = Clock.systemUTC();
        System.out.println("Clock:"+clock);

        //根据系统时钟区域返回时间
        Clock defaultClock = Clock.systemDefaultZone();
        System.out.println("Clock:"+clock);
    }

    //判断日期是早于还是晚于另一个日期
    @Test
    public void isBeforeOrIsAfter(){
        //LocalDate 类有两类方法 isBefore() 和 isAfter() 用于比较日期。调用 isBefore() 方法时，如果给定日期小于当前日期则返回 true。
        LocalDate today = LocalDate.now();
        LocalDate tomorrow = LocalDate.of(2022, 1, 29);
        if(tomorrow.isAfter(today)){
            System.out.println("Tomorrow comes after today");
        }
        //减去一天
        LocalDate yesterday = today.minus(1,ChronoUnit.DAYS);
        if(yesterday.isBefore(today)){
            System.out.println("Yesterday is day befores today");
        }
    }

    //处理时区
    @Test
    public void getZonTime(){
        //Java 8不仅分离了日期和时间，也把时区分离出来了。现在有一系列单独的类如 ZoneId 来处理特定时区，ZoneDateTime 类来表示某时区下的时间。
        //设置时区
        ZoneId america = ZoneId.of("America/New_York");

        LocalDateTime localDateTime = LocalDateTime.now();

        ZonedDateTime dateTime = ZonedDateTime.of(localDateTime,america);
        System.out.println("现在的日期和时间在特定的时区:"+dateTime);
    }

    //如何体现固定日期
    @Test
    public void checkCardExpiry(){
        //使用YearMonth类处理特定的日期
        //表示信用卡到期这类固定日期。与 MonthDay 检查重复事件的例子相似， YearMonth 是另一个组合类，用于表示信用卡到期日、FD到期日、期货期权到期日等
        YearMonth currentYearMonth = YearMonth.now();
        log.info("days in month year:{},{},{}",currentYearMonth,currentYearMonth.lengthOfMonth(),currentYearMonth.lengthOfYear());

        //还可以用这个类得到 当月共有多少天，YearMonth 实例的 lengthOfMonth() 方法可以返回当月的天数，在判断2月有28天还是29天时非常有用。
        YearMonth creditCardExpiry = YearMonth.of(2028, Month.FEBRUARY);
        System.out.printf("you credit card expires on %s %n",creditCardExpiry);
    }

    //检查闰年
    @Test
    public void isleapYear(){
        LocalDate today = LocalDate.now();
        if(today.isLeapYear()){
            System.out.println("This year is leap year");
        }else{
            System.out.println("2022 is not a leap year");
        }
    }

    //计算两个日期之间的天数和月数
    @Test
    public void calcDateDays(){
        //有一个常见日期操作是计算两个日期之间的天数、周数或月数。在Java 8中可以用java.time.Period类来做计算。下面这个例子中，我们计算了当天和将来某一天之间的月数
        LocalDate today = LocalDate.now();
        LocalDate java8Release = LocalDate.of(2018, Month.MAY, 14);
        Period period = Period.between(today, java8Release);
        System.out.println("相差:"+period.getMonths());
    }

    //包含时差信息的日期和时间
    @Test
    public void ZoneOffset(){
        //ZoneOffset类用来表示时区，举例来说印度与GMT或UTC标准时区相差+05:30，可以通过ZoneOffset.of()静态方法来 获取对应的时区。
        // 一旦得到了时差就可以通过传入LocalDateTime和ZoneOffset来创建一个OffSetDateTime对象。
        LocalDateTime dateTime = LocalDateTime.of(2018, Month.FEBRUARY,14,19,30);
        ZoneOffset offset = ZoneOffset.of("+05:30");
        OffsetDateTime dateTime1  = OffsetDateTime.of(dateTime,offset);
        System.out.println("date an time with timezone offset in java:"+dateTime1);
    }

    //获取当前的时间戳
    @Test
    public void getTimeStamp(){
        //Instant类有一个静态工厂方法now()会返回当前的时间戳
        Instant timestamp = Instant.now();
        System.out.println("what is value of this instant:"+timestamp);
    }

    //使用预定义的格式化工具取解析或者格式化日期
    @Test
    public void formateDate(){
        //Java 8引入了全新的日期时间格式工具，线程安全而且使用方便。它自带了一些常用的内置格式化工具
        String dayAfterTommorrow = "20180120";
        LocalDate formatted = LocalDate.parse(dayAfterTommorrow, DateTimeFormatter.BASIC_ISO_DATE);
        System.out.printf("Date generated from String %s is %s %n",dayAfterTommorrow,formatted);
    }
}
